#*******************************************# # GInfo 数据、图片、运转信息采集 接口说明 # #*******************************************# 一、用途 可用于通过非客户端的快递业务数据的直接录入,比如通过移动GPRS通道,使用手持终端进行取件录单、转运、派送签收图片等处理。 一、数据接口约定 1、协议:http 2、接口名称:/cgi-bin/GInfo.dll?EmsTrans 3、接口请求方式:POST,text/xml; charset=gbk 4、POST数据标记定义 0操作,数字0-9,含义:0取件,1转运,2派送,3签收,4超时,5扣关,6错误,7丢失,8退件,9异常 YYYY.MM.DD HH:MM:SS操作时间 GG12345手持终端编号,1-30字符 CGG553客户帐号1-15字符 13916365333客户短信号码0-22字符 EM66232332运单号:8-30字母数字或者连字符- EM66232332转单号:8-30字母数字或者连字符- EM66232332参考号:8-30字母数字或者连字符-,该号码回传 TNT快递类别,渠道:0-15字符,与系统设置对应 1件数,数字 0包裹类型,数字:0文件,1包裹,2防水袋 2.345重量公斤,三位小数精度 0运费付款方式,数字:0月结,1现付,2到付 PP结算指示,0-3字符:PP,CC,COD,PD 3.54运费,两位小数精度 电视机物品名称,0-254字符 23.45代收货款,两位小数精度 出发地0-63字符 目的地1-63字符,可以使用EMMis能够识别的编码,有编码,电话区号等,条件是与快递类别绑定过 标签0-15字符 签收人0-30字符 备注0-254字符 JPG3字符,大写:BMP,JPG,GIF,PNG 图片数据base64编码 ac003b5fac003b5fac003b5fac003b5f *任何请求,为必须的字段,除标记外,其它标记的位置顺序随意,注意会影响MD5编码 *如果OP值为3(签收),必须有标记字段 *标记为最后一个标记,其值为前面的内容附加上密钥后的MD5编码的16进制字串,特别注意,密钥前面的字符一定为“>”,回车换行符将被清除,编码时要注意! 5、返回数据定义:格式文本:返回码\r\n参考号 返回码为一整数,参考号为信息回传,按照标记定义 所有小于零的返回码均表示请求失败,大于零的编码为EMMis系统中的记录ID 返回错误码定义: -1 :用户不存在,手持终端编号对应的系统用户不存在 -2 :客户不存在,客户账号错误,并且系统中没有开设名称为“现金”的散客帐户,作为找不到客户时的替代 -5 :数据错误,提供的数据不完整或者不符合要求 -6 :没有MD5签名数据 -7 :MD5签名校验失败,请注意密钥的统一! -9 :数据库错误,GInfo平台问题 -10:数据错误 -11:数据错误 -12:数据错误 -13:数据错误 -14:数据错误 -15:数据错误,为3时,必须定义此标记内容 -16:数据不合法,检查格式是否正确:YYYY.MM.DD hh:mm:ss #----------------------- 上海钮门网络科技有限公司 2008.12.04 **附:C++ HTTP POST 专用请求函数及例子,供参考 //----------------------- /* 函数:EmsPost:向GInfo平台的数据传送接口发送请求 参数: pszHost:http服务器的域名或者ip地址 pszApi:接口位置,规定为:/cgi-bin/GInfo.dll?EmsTrans pszParam:POST数据,标记封装 pszGet :接收缓存,空间不小于1024字节 返回值:pszGet接收的字节数,小于或等于0为失败 pszGet中的数据含义 格式:状态码\r\n参考号 状态码定义如下: 1、小于或者等于0,错误,含义见文档 2、大于零:成功,该数字为EMMis中的记录ID */ int EmsPost(const char *pszHost, const char *pszApi, const char *pszParam, char *pszGet) { sockaddr_in sin; SOCKET sock = socket (AF_INET, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) return -100; sin.sin_family = AF_INET; sin.sin_port = htons( (unsigned short)80); struct hostent * host_addr = gethostbyname(pszHost); if(host_addr==NULL) { closesocket(sock); return -103; } sin.sin_addr.s_addr = *((int*)*host_addr->h_addr_list) ; int TimeOut=60000; if(::setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR) { closesocket(sock); return -120; } if(::setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR) { closesocket(sock); return -120; } unsigned long ul = 1; int ret = ioctlsocket(sock, FIONBIO, (unsigned long*)&ul); if(ret==SOCKET_ERROR) { closesocket(sock); return -120; } //--尝试建立与服务器的连接 connect (sock,(const struct sockaddr *)&sin, sizeof(sockaddr_in) );//MAY ERROR struct timeval timeout ; fd_set r; FD_ZERO(&r); FD_SET(sock, &r); timeout.tv_sec = 60; timeout.tv_usec =0; ret = select(0, 0, &r, 0, &timeout); if ( ret <= 0 ) { ::closesocket(sock); return -120; } unsigned long ul1= 0 ; ret = ioctlsocket(sock, FIONBIO, (unsigned long*)&ul1); if(ret==SOCKET_ERROR) { ::closesocket (sock); return -120; } //--与服务器的连接建立成功 //--构造 http 请求头--- char *b,*p; b = pszGet + 512; sprintf(b, "POST %s HTTP/1.0\r\n" "Accept: */*\r\n" "Host: %s\r\n" "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\n" "Content-Length: %d\r\n" "Content-Type: text/xml; charset=gbk\r\n\r\n", pszApi, pszHost, strlen(pszParam)); //--发送请求数据 send(sock,b,strlen(b),0); send(sock,pszParam,strlen(pszParam),0); //--发送完毕 char * pEnd=pszGet+1023; p=pszGet; //-- 获取响应状态行 while(recv(sock, p, 1, 0) > 0 && p < pEnd) { if(*p == '\n') break; p++; } *p = '\0'; if( strstr(pszGet,"200") == NULL) { closesocket(sock); return -102; } //--获取其它响应头标-- b=p; while(recv(sock, p, 1, 0) > 0 && p < pEnd) { if(*p == '\n') { if(p-b < 5) break; b=p; } p++; } //--获取响应实体,保存在pszGet中 p=pszGet; while(recv(sock,p,1,0) > 0 && p < pEnd) p++; *p = '\0'; closesocket(sock); return (p-pszGet); } //****************************** //****调用例子1、取件数据******* char szHost[] ="www.test.cn"; char szGet[1024]={0}; char szKey[32]="abcdefg1234567"; char szParam[1024]={0}; strcpy(szParam, "0\r\n" "2008.11.04 10:01:01\r\n" "pd55663444cn\r\n" "lhgz\r\n" "PDA000001\r\n" "PDA000001R\r\n" "2\r\n" "0\r\n" "1.234\r\n" "0\r\n" "PP\r\n" "33.33\r\n" "电视机\r\n" "23.45\r\n" "北京\r\n" "美国\r\n" "PDA传输"); char *p = szParam; p += strlen(p); strcpy(p,szKey); char szMD5[36]={0}; MD5((unsigned char *)szParam,strlen(szParam),szMD5); sprintf(p, "\r\n%s", szMD5); int iLen = EmsPost( szHost, "/cgi-bin/GInfo.dll?EmsTrans", szParam, szGet); //**** 调用例子1结束***** //****调用例子2、签收数据(含图片c:\1.jpg)******* char szHost[] ="www.test.cn"; char szGet[1024]={0}; char szKey[32]="abcdefg1234567"; char szParam[128000]={0}; strcpy(szParam, "3\r\n" "2008.11.04 10:01:01\r\n" "pd55663444cn\r\n" "lhgz\r\n" "PDA000001\r\n" "PDA000001R\r\n" "2\r\n" "0\r\n" "1.234\r\n" "0\r\n" "33.33\r\n" "电视机\r\n" "23.45\r\n" "北京\r\n" "美国\r\n" "PDA传输\r\n" "公司盖章\r\n" "JPG\r\n" ""); char *p = szParam; p += strlen(p); CFile f; f.Open("c:\\1.jpg",CFile::modeRead); BYTE buf[64000]; int iLen = f.GetLength(); f.Read(buf,iLen); f.Close(); unsigned int ioLen=0; Base64Encode((const char *)buf,iLen,p,120000,&ioLen); p+= ioLen; strcpy(p,""); p += strlen(p); strcpy(p,szKey); char szMD5[36]={0}; MD5((unsigned char *)szParam,strlen(szParam),szMD5); sprintf(p, "\r\n%s", szMD5); iLen = EmsPost( szHost, "/cgi-bin/GInfo.dll?EmsTrans", szParam, szGet); //**** 调用例子2结束*****